package it.polimi.digitalstate.manager;

import java.sql.Date;
import java.util.ArrayList;

import it.polimi.digitalstate.entities.Citizen;
import it.polimi.digitalstate.entities.Election;
import it.polimi.digitalstate.entities.ElectionVote;
import it.polimi.digitalstate.entities.Joinrequest;
import it.polimi.digitalstate.entities.Party;
import it.polimi.digitalstate.entities.User;
import it.polimi.digitalstate.dto.CitizenDTO;
import it.polimi.digitalstate.dto.ElectionDTO;
import it.polimi.digitalstate.dto.ElectionVoteDTO;
import it.polimi.digitalstate.dto.JoinrequestDTO;
import it.polimi.digitalstate.dto.PartyDTO;

import javax.annotation.security.RolesAllowed;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import managerexception.CannotSaveElection;
import managerexception.CannotSendElectionVote;

/**
 * Session Bean implementation class ElectionManager
 */
@LocalBean
@Stateless
public class ElectionManager implements ElectionManagerLocal {

    /**
     * Default constructor. 
     */
	@PersistenceContext
	private EntityManager em;
	
    public ElectionManager() {
        // TODO Auto-generated constructor stub
    }

	@RolesAllowed({"governor"})
	@Override
	public void createNewElection(ElectionDTO election_dto) throws CannotSaveElection {
		if(correctElectionDates(election_dto))
			{				
				em.persist(
						new Election(
								election_dto.getName(),
								(User)DTOEntityTransformer.getEntity(em, election_dto.getGovernor()),
								election_dto.getCandidacystartdate(),
								election_dto.getCandidacyenddate(),
								election_dto.getElectionstartdate(),
								election_dto.getElectionenddate()
								)
						);
			}
		else{
			throw new CannotSaveElection();
		}
				
	}

	@Override
	public boolean correctElectionDates(ElectionDTO election_dto){
		return PreconditionCheck.correctElectionDates(election_dto, em);
	}


	@Override
	public boolean hasElectionVoted(CitizenDTO citizen, ElectionDTO election) {
		//TODO
		return false;
	}
//	@RolesAllowed({"CITIZEN"})
	@Override
    public void submitElectionVote(ElectionVoteDTO electionvote) throws managerexception.CannotSendElectionVote {
		if(!hasAlreadyElectionVoted( electionvote.getCitizen()) && electionIsOpen()){
		
		em.persist(
				new ElectionVote(
						(Citizen)DTOEntityTransformer.getEntity(em, electionvote.getCitizen()),
						(Party)DTOEntityTransformer.getEntity(em, electionvote.getParty()),
						(Citizen)DTOEntityTransformer.getEntity(em, electionvote.getP1()),
						(electionvote.getP2() == null) ? null :(Citizen)DTOEntityTransformer.getEntity(em, electionvote.getP2()),
						(electionvote.getP3()== null)? null :(Citizen)DTOEntityTransformer.getEntity(em, electionvote.getP3()),
						new Date((new java.util.Date()).getTime()),
						PreconditionCheck.getCurrentElection(em)
						)
				);
		}else{
			throw new CannotSendElectionVote();
		}
	}
	
	@Override
	public boolean hasAlreadyElectionVoted(CitizenDTO citizen) {
		return PreconditionCheck.hasElectionVoted(citizen, em);
	}   
	
	@Override
    public boolean electionIsOpen(){
		return PreconditionCheck.rightElectionTime(em);
	}
	
	@SuppressWarnings("unused")
	private void acceptRequest(JoinrequestDTO request){
		//TODO implement @Mohamed
	}
	@SuppressWarnings("unused")
	private void denyRequest(JoinrequestDTO request){
		//TODO implement @Mohamed
	}

	@Override
	public boolean isElection(){
		return PreconditionCheck.rightElectionTime(em);
	}
	@Override
	public boolean isCandidacy(){
		return PreconditionCheck.rightCandidacyTime(em);
	}
	@Override
	public String getElectionNames(){
		Election e =  PreconditionCheck.getCurrentElection(em);
		if(e==null)
			return "There isn't any election at this time";
		return e.getName();
	}
	
	@Override
	public ElectionVoteDTO[] getElectionResults() {
		Query q = em.createNamedQuery("electionvote_getByElection");
		q.setParameter("election", PreconditionCheck.getCurrentElection(em));
		Object[] o = q.getResultList().toArray();
		ElectionVoteDTO[] ret = new ElectionVoteDTO[o.length];
		for(int i=0;i<o.length;i++)
			ret[i]=(ElectionVoteDTO) ((ElectionVote)o[i]).getDTO();
		return ret;
	}
}
